﻿using System;
using System.Diagnostics;
using static SmartSite.Common.CheckingNullArgument;
using static SmartSite.Frame.FrameTypeEnum;

namespace SmartSite.Frame
{
    public class StatusReqFrame : WithCommunicationIdFrame
    {
        readonly FrameTypeEnum _Key = StatusReqFrameType;
        public override FrameTypeEnum Key { get { return _Key; } }

        /// <summary>
        /// 采样时间
        /// </summary>
        readonly IValueField<DateTime> CreateTimeField;
        public DateTime CreateTime
        {
            get => CreateTimeField.Value;
            set => CreateTimeField.Value = value;
        }

        /// <summary>
        /// 回转角度
        /// </summary>
        /// <value></value>
        readonly IValueField<float> RotationAngleField;
        public float RotationAngle
        {
            get => RotationAngleField.Value;
            set => RotationAngleField.Value = value;
        }

        /// <summary>
        /// 小车范围幅度值，以0.1米为单位，范围0米-6553.5米
        /// </summary>
        /// <value></value>
        readonly IValueField<float> CarRangeField;
        public float CarRange
        {
            get => CarRangeField.Value;
            set
            {
                if (value < 0 || value > 6553.5)
                    throw new ArgumentOutOfRangeException(nameof(CarRange));

                CarRangeField.Value = value;
            }
        }

        /// <summary>
        /// 高度
        /// </summary>
        /// <value>16 位, 无符号</value>
        readonly IValueField<float> HookHeighField;
        public float HookHeigh
        {
            get => HookHeighField.Value;
            set => HookHeighField.Value = value;
        }

        /// <summary>
        /// 称重
        /// </summary>
        /// <value>16 位, 无符号, 精度 0.01</value>
        readonly IValueField<float> RealWeightField;
        public float RealWeight
        {
            get => RealWeightField.Value;
            set => RealWeightField.Value = value;
        }

        /// <summary>
        /// 当前力矩所占最大力矩的百分比，范围为0 -255
        /// </summary>
        /// <value>8 位, 0-255</value>
        readonly IValueField<Byte> MomentField;
        public byte Moment
        {
            get => MomentField.Value;
            set => MomentField.Value = value;
        }

        // TODO: 以下与成都市建委协议不同

        /// <summary>
        /// 刹车角度
        /// </summary>
        /// <value>8 位</value>
        readonly IValueField<float> BrakeAngleField;
        public float BrakeAngle
        {
            get => BrakeAngleField.Value;
            set => BrakeAngleField.Value = value;
        }

        /// <summary>
        /// 风速
        /// </summary>
        /// <value>16 位</value>
        readonly IValueField<float> WindSpeedField;
        public float WindSpeed
        {
            get => WindSpeedField.Value;
            set => WindSpeedField.Value = value;
        }

        /// <summary>
        /// 塔身倾斜 X 方向
        /// </summary>
        /// <value>8 位, 精度 0.1</value>
        readonly IValueField<float> CraneTiltXField;
        public float CraneTiltX
        {
            get => CraneTiltXField.Value;
            set => CraneTiltXField.Value = value;
        }

        /// <summary>
        /// 塔身倾斜 Y 方向
        /// </summary>
        /// <value>8 位, 精度 0.1</value>
        readonly IValueField<float> CraneTiltYField;
        public float CraneTiltY
        {
            get => CraneTiltYField.Value;
            set => CraneTiltYField.Value = value;
        }

        readonly IValueField<byte> NotUsedAlarmCodeField1;
        readonly IValueField<byte> NotUsedAlarmCodeField2;

        /// <summary>
        /// 低限位警报代码
        /// </summary>
        /// <value>4 位</value>
        readonly IValueField<byte> LowLimitAlarmCodeField;
        public int LowLimitAlarmCode
        {
            get => LowLimitAlarmCodeField.Value;
            set => LowLimitAlarmCodeField.Value = (byte)value;
        }

        /// <summary>
        /// 高限位警报代码
        /// </summary>
        /// <value>4 位</value>
        readonly IValueField<byte> HighLimitAlarmCodeField;
        public int HighLimitAlarmCode
        {
            get => HighLimitAlarmCodeField.Value;
            set => HighLimitAlarmCodeField.Value = (byte)value;
        }

        /// <summary>
        /// 近限位警报代码
        /// </summary>
        /// <value>4 位</value>
        readonly IValueField<byte> NearLimitAlarmCodeField;
        public int NearLimitAlarmCode
        {
            get => NearLimitAlarmCodeField.Value;
            set => NearLimitAlarmCodeField.Value = (byte)value;
        }

        /// <summary>
        /// 远限位警报代码
        /// </summary>
        /// <value>4 位</value>
        readonly IValueField<byte> FarLimitAlarmCodeField;
        public int FarLimitAlarmCode
        {
            get => FarLimitAlarmCodeField.Value;
            set => FarLimitAlarmCodeField.Value = (byte)value;
        }

        /// <summary>
        /// 右限位警报代码
        /// </summary>
        /// <value>4 位</value>
        readonly IValueField<byte> RightLimitAlarmCodeField;
        public int RightLimitAlarmCode
        {
            get => RightLimitAlarmCodeField.Value;
            set => RightLimitAlarmCodeField.Value = (byte)value;
        }

        /// <summary>
        /// 左限位警报代码
        /// </summary>
        /// <value>4 位</value>
        readonly IValueField<byte> LeftLimitAlarmCodeField;
        public int LeftLimitAlarmCode
        {
            get => LeftLimitAlarmCodeField.Value;
            set => LeftLimitAlarmCodeField.Value = (byte)value;
        }

        readonly IValueField<byte> NotUsedAlarmCodeField3;

        /// <summary>
        /// 塔身倾角警报代码
        /// </summary>
        /// <value>8 位</value>
        readonly IValueField<byte> CraneTiltAngleAlarmCodeField;  // TODO: 这个代码怎么这么长? 目前做 4 位处理，高位用 NotUsedAlarmCode3 占位
        public int CraneTiltAngleAlarmCode
        {
            get => CraneTiltAngleAlarmCodeField.Value;
            set => CraneTiltAngleAlarmCodeField.Value = (byte)value;
        }

        readonly IValueField<byte> NotUsedAlarmCodeField4;
        readonly IValueField<byte> NotUsedAlarmCodeField5;
        readonly IValueField<byte> NotUsedAlarmCodeField6;

        /// <summary>
        /// 风速警报代码
        /// </summary>
        /// <value>8 位</value>
        readonly IValueField<byte> WindSpeedAlarmCodeField; // TODO: 这个代码怎么这么长? 目前做 4 位处理，高位用 NotUsedAlarmCode6 占位
        public int WindSpeedAlarmCode
        {
            get => WindSpeedAlarmCodeField.Value;
            set => WindSpeedAlarmCodeField.Value = (byte)value;
        }

        /// <summary>
        /// 力矩警报代码
        /// </summary>
        /// <value>4 位</value>
        readonly IValueField<byte> MomentAlarmCodeField;
        public int MomentAlarmCode
        {
            get => MomentAlarmCodeField.Value;
            set => MomentAlarmCodeField.Value = (byte)value;
        }

        /// <summary>
        /// 起吊重量警报代码
        /// </summary>
        /// <value>4 位</value>
        readonly IValueField<byte> StartWeightAlarmCodeField; // TODO: 这是重量? 目前做警报代码处理dd
        public int StartWeightAlarmCode
        {
            get => StartWeightAlarmCodeField.Value;
            set => StartWeightAlarmCodeField.Value = (byte)value;
        }

        readonly IValueField<byte> NotUsedAlarmCodeField7;
        readonly IValueField<byte> NotUsedAlarmCodeField8;
        readonly IValueField<byte> NotUsedAlarmCodeField9;

        /// <summary>
        /// 低碰撞报警编码
        /// </summary>
        readonly IValueField<byte> LowTowerCollidedAlarmCodeField;
        public int LowTowerCollidedAlarmCode
        {
            get => LowTowerCollidedAlarmCodeField.Value;
            set => LowTowerCollidedAlarmCodeField.Value = (byte)value;
        }

        /// <summary>
        /// 近碰撞报警编码
        /// </summary>
        readonly IValueField<byte> NearTowerCollidedAlarmCodeField;
        public int NearTowerCollidedAlarmCode
        {
            get => NearTowerCollidedAlarmCodeField.Value;
            set => NearTowerCollidedAlarmCodeField.Value = (byte)value;
        }

        /// <summary>
        /// 远碰撞报警代码
        /// </summary>
        readonly IValueField<byte> FarTowerCollidedAlarmCodeField;
        public int FarTowerCollidedAlarmCode
        {
            get => FarTowerCollidedAlarmCodeField.Value;
            set => FarTowerCollidedAlarmCodeField.Value = (byte)value;
        }

        /// <summary>
        /// 右碰撞报警代码
        /// </summary>
        readonly IValueField<byte> RightTowerCollidedAlarmCodeField;
        public int RightTowerCollidedAlarmCode
        {
            get => RightTowerCollidedAlarmCodeField.Value;
            set => RightTowerCollidedAlarmCodeField.Value = (byte)value;
        }

        /// <summary>
        /// 右碰撞报警代码
        /// </summary>
        readonly IValueField<byte> LeftTowerCollidedAlarmCodeField;
        public int LeftTowerCollidedAlarmCode
        {
            get => LeftTowerCollidedAlarmCodeField.Value;
            set => LeftTowerCollidedAlarmCodeField.Value = (byte)value;
        }

        readonly IValueField<byte> NotUsedAlarmCodeField10;
        readonly IValueField<byte> NotUsedAlarmCodeField11;
        readonly IValueField<byte> NotUsedAlarmCodeField12;
        readonly IValueField<byte> NotUsedAlarmCodeField13;

        /// <summary>
        /// 近方禁行区报警代码
        /// </summary>
        readonly IValueField<byte> NearForbiddenZoneCollidedAlarmCodeField;
        public int NearForbiddenZoneCollidedAlarmCode
        {
            get => NearForbiddenZoneCollidedAlarmCodeField.Value;
            set => NearForbiddenZoneCollidedAlarmCodeField.Value = (byte)value;
        }

        /// <summary>
        /// 远方禁行区报警代码
        /// </summary>
        readonly IValueField<byte> FarForbiddenZoneCollidedAlarmCodeField;
        public int FarForbiddenZoneCollidedAlarmCode
        {
            get => FarForbiddenZoneCollidedAlarmCodeField.Value;
            set => FarForbiddenZoneCollidedAlarmCodeField.Value = (byte)value;
        }

        /// <summary>
        /// 右方禁行区报警代码
        /// </summary>
        readonly IValueField<byte> RightForbiddenZoneCollidedAlarmCodeField;
        public int RightForbiddenZoneCollidedAlarmCode
        {
            get => RightForbiddenZoneCollidedAlarmCodeField.Value;
            set => RightForbiddenZoneCollidedAlarmCodeField.Value = (byte)value;
        }

        /// <summary>
        /// 左方禁行区报警代码
        /// </summary>
        readonly IValueField<byte> LeftForbiddenZoneCollidedAlarmCodeField;
        public int LeftForbiddenZoneCollidedAlarmCode
        {
            get => LeftForbiddenZoneCollidedAlarmCodeField.Value;
            set => LeftForbiddenZoneCollidedAlarmCodeField.Value = (byte)value;
        }

        readonly IValueField<byte> NotUsedAlarmCodeField14;
        readonly IValueField<byte> NotUsedAlarmCodeField15;
        readonly IValueField<byte> NotUsedAlarmCodeField16;

        /// <summary>
        /// 低障碍碰撞报警代码
        /// </summary>
        readonly IValueField<byte> LowObstacleCollidedAlarmCodeField;
        public int LowObstacleCollidedAlarmCode
        {
            get => LowObstacleCollidedAlarmCodeField.Value;
            set => LowObstacleCollidedAlarmCodeField.Value = (byte)value;
        }

        /// <summary>
        /// 近方障碍碰撞报警代码
        /// </summary>
        readonly IValueField<byte> NearObstacleCollidedAlarmCodeField;
        public int NearObstacleCollidedAlarmCode
        {
            get => NearObstacleCollidedAlarmCodeField.Value;
            set => NearObstacleCollidedAlarmCodeField.Value = (byte)value;
        }

        /// <summary>
        /// 远方障碍碰撞报警代码
        /// </summary>
        readonly IValueField<byte> FarObstacleCollidedAlarmCodeField;
        public int FarObstacleCollidedAlarmCode
        {
            get => FarObstacleCollidedAlarmCodeField.Value;
            set => FarObstacleCollidedAlarmCodeField.Value = (byte)value;
        }

        /// <summary>
        /// 右方障碍碰撞报警代码
        /// </summary>
        readonly IValueField<byte> RightObstacleCollidedAlarmCodeField;
        public int RightObstacleCollidedAlarmCode
        {
            get => RightObstacleCollidedAlarmCodeField.Value;
            set => RightObstacleCollidedAlarmCodeField.Value = (byte)value;
        }

        /// <summary>
        /// 左方障碍碰撞报警代码
        /// </summary>
        readonly IValueField<byte> LeftObstacleCollidedAlarmCodeField;
        public int LeftObstacleCollidedAlarmCode
        {
            get => LeftObstacleCollidedAlarmCodeField.Value;
            set => LeftObstacleCollidedAlarmCodeField.Value = (byte)value;
        }

        /// <summary>
        /// 右方继电输出编码
        /// </summary>
        readonly IValueField<byte> RightRelayOutPutCodeField;
        public int RightRelayOutPutCode
        {
            get => RightRelayOutPutCodeField.Value;
            set => RightRelayOutPutCodeField.Value = (byte)value;
        }

        /// <summary>
        /// 左方继电输出编码
        /// </summary>
        readonly IValueField<byte> LeftRelayOutPutCodeField;
        public int LeftRelayOutPutCode
        {
            get => LeftRelayOutPutCodeField.Value;
            set => LeftRelayOutPutCodeField.Value = (byte)value;
        }

        /// <summary>
        /// 近方继电输出编码
        /// </summary>
        readonly IValueField<byte> NearRelayOutPutCodeField;
        public int NearRelayOutPutCode
        {
            get => NearRelayOutPutCodeField.Value;
            set => NearRelayOutPutCodeField.Value = (byte)value;
        }

        /// <summary>
        /// 远方继电输出编码
        /// </summary>
        readonly IValueField<byte> FarRelayOutPutCodeField;
        public int FarRelayOutPutCode
        {
            get => FarRelayOutPutCodeField.Value;
            set => FarRelayOutPutCodeField.Value = (byte)value;
        }

        /// <summary>
        /// 低方继电输出编码
        /// </summary>
        readonly IValueField<byte> LowRelayOutPutCodeField;
        public int LowRelayOutPutCode
        {
            get => LowRelayOutPutCodeField.Value;
            set => LowRelayOutPutCodeField.Value = (byte)value;
        }


        /// <summary>
        /// 高方继电输出编码
        /// </summary>
        readonly IValueField<byte> HighRelayOutPutCodeField;
        public int HighRelayOutPutCode
        {
            get => HighRelayOutPutCodeField.Value;
            set => HighRelayOutPutCodeField.Value = (byte)value;
        }

        readonly IValueField<byte> NotUsedRelayOutPutCodeField1;
        readonly IValueField<byte> NotUsedRelayOutPutCodeField2;

        public StatusReqFrame() : this(Array.Empty<byte>()) => InitFieldValue();

        protected StatusReqFrame(byte[] buffer)
        : base(CheckingNull(buffer, nameof(buffer)))
        {
            CreateTimeField = new DateTimeField(CommunicationIdField);
            RotationAngleField = new ScaledFloatField(CreateTimeField, 16, 10);
            CarRangeField = new ScaledUnsignedFloatField(RotationAngleField, 16, 10);
            HookHeighField = new ScaledFloatField(CarRangeField, 16, 10);
            RealWeightField = new ScaledUnsignedFloatField(HookHeighField, 16, 100);
            MomentField = new ByteField(RealWeightField, 8);
            BrakeAngleField = new ScaledFloatField(MomentField, 8, 1);
            WindSpeedField = new ScaledFloatField(BrakeAngleField, 16, 10);
            CraneTiltXField = new ScaledFloatField(WindSpeedField, 8, 10);
            CraneTiltYField = new ScaledFloatField(CraneTiltXField, 8, 10);

            Debug.Assert(6 << 3 == (int)CreateTimeField.Index);
            Debug.Assert(10 << 3 == (int)RotationAngleField.Index);
            Debug.Assert(12 << 3 == (int)CarRangeField.Index);
            Debug.Assert(14 << 3 == (int)HookHeighField.Index);
            Debug.Assert(16 << 3 == (int)RealWeightField.Index);
            Debug.Assert(18 << 3 == (int)MomentField.Index);
            Debug.Assert(19 << 3 == (int)BrakeAngleField.Index);
            Debug.Assert(20 << 3 == (int)WindSpeedField.Index);
            Debug.Assert(22 << 3 == (int)CraneTiltXField.Index);
            Debug.Assert(23 << 3 == (int)CraneTiltYField.Index);


            /*
             * 以下
             * 限位报警编号
             */
            NotUsedAlarmCodeField1 = new ByteField(CraneTiltYField, 4);
            NotUsedAlarmCodeField2 = new ByteField(NotUsedAlarmCodeField1, 4);
            LowLimitAlarmCodeField = new ByteField(NotUsedAlarmCodeField2, 4);
            HighLimitAlarmCodeField = new ByteField(LowLimitAlarmCodeField, 4);
            NearLimitAlarmCodeField = new ByteField(HighLimitAlarmCodeField, 4);
            FarLimitAlarmCodeField = new ByteField(NearLimitAlarmCodeField, 4);
            RightLimitAlarmCodeField = new ByteField(FarLimitAlarmCodeField, 4);
            LeftLimitAlarmCodeField = new ByteField(RightLimitAlarmCodeField, 4);

            Debug.Assert(24 << 3 == (int)NotUsedAlarmCodeField1.Index);
            Debug.Assert((24 << 3) + 4 == (int)NotUsedAlarmCodeField2.Index);
            Debug.Assert(25 << 3 == (int)LowLimitAlarmCodeField.Index);
            Debug.Assert((25 << 3) + 4 == (int)HighLimitAlarmCodeField.Index);
            Debug.Assert(26 << 3 == (int)NearLimitAlarmCodeField.Index);
            Debug.Assert((26 << 3) + 4 == (int)FarLimitAlarmCodeField.Index);
            Debug.Assert(27 << 3 == (int)RightLimitAlarmCodeField.Index);
            Debug.Assert((27 << 3) + 4 == (int)LeftLimitAlarmCodeField.Index);

            /*
             * 以下
             * 其他报警编码
             */
            NotUsedAlarmCodeField3 = new ByteField(LeftLimitAlarmCodeField, 4);
            CraneTiltAngleAlarmCodeField = new ByteField(NotUsedAlarmCodeField3, 4);
            NotUsedAlarmCodeField4 = new ByteField(CraneTiltAngleAlarmCodeField, 4);
            NotUsedAlarmCodeField5 = new ByteField(NotUsedAlarmCodeField4, 4);
            NotUsedAlarmCodeField6 = new ByteField(NotUsedAlarmCodeField5, 4);
            WindSpeedAlarmCodeField = new ByteField(NotUsedAlarmCodeField6, 4);
            MomentAlarmCodeField = new ByteField(WindSpeedAlarmCodeField, 4);
            StartWeightAlarmCodeField = new ByteField(MomentAlarmCodeField, 4);

            Debug.Assert(28 << 3 == (int)NotUsedAlarmCodeField3.Index);
            Debug.Assert((28 << 3) + 4 == (int)CraneTiltAngleAlarmCodeField.Index);
            Debug.Assert(29 << 3 == (int)NotUsedAlarmCodeField4.Index);
            Debug.Assert((29 << 3) + 4 == (int)NotUsedAlarmCodeField5.Index);
            Debug.Assert(30 << 3 == (int)NotUsedAlarmCodeField6.Index);
            Debug.Assert((30 << 3) + 4 == (int)WindSpeedAlarmCodeField.Index);
            Debug.Assert(31 << 3 == (int)MomentAlarmCodeField.Index);
            Debug.Assert((31 << 3) + 4 == (int)StartWeightAlarmCodeField.Index);

            /*
             * 以下
             * 塔机碰撞报警编码
             */
            NotUsedAlarmCodeField7 = new ByteField(StartWeightAlarmCodeField, 4);
            NotUsedAlarmCodeField8 = new ByteField(NotUsedAlarmCodeField7, 4);
            NotUsedAlarmCodeField9 = new ByteField(NotUsedAlarmCodeField8, 4);
            LowTowerCollidedAlarmCodeField = new ByteField(NotUsedAlarmCodeField9, 4);
            NearTowerCollidedAlarmCodeField = new ByteField(LowTowerCollidedAlarmCodeField, 4);
            FarTowerCollidedAlarmCodeField = new ByteField(NearTowerCollidedAlarmCodeField, 4);
            RightTowerCollidedAlarmCodeField = new ByteField(FarTowerCollidedAlarmCodeField, 4);
            LeftTowerCollidedAlarmCodeField = new ByteField(RightTowerCollidedAlarmCodeField, 4);

            Debug.Assert(32 << 3 == (int)NotUsedAlarmCodeField7.Index);
            Debug.Assert((32 << 3) + 4 == (int)NotUsedAlarmCodeField8.Index);
            Debug.Assert(33 << 3 == (int)NotUsedAlarmCodeField9.Index);
            Debug.Assert((33 << 3) + 4 == (int)LowTowerCollidedAlarmCodeField.Index);
            Debug.Assert(34 << 3 == (int)NearTowerCollidedAlarmCodeField.Index);
            Debug.Assert((34 << 3) + 4 == (int)FarTowerCollidedAlarmCodeField.Index);
            Debug.Assert(35 << 3 == (int)RightTowerCollidedAlarmCodeField.Index);
            Debug.Assert((35 << 3) + 4 == (int)LeftTowerCollidedAlarmCodeField.Index);

            /*
             * 以下
             * 禁止区碰撞报警编码
             */
            NotUsedAlarmCodeField10 = new ByteField(LeftTowerCollidedAlarmCodeField, 4);
            NotUsedAlarmCodeField11 = new ByteField(NotUsedAlarmCodeField10, 4);
            NotUsedAlarmCodeField12 = new ByteField(NotUsedAlarmCodeField11, 4);
            NotUsedAlarmCodeField13 = new ByteField(NotUsedAlarmCodeField12, 4);
            NearForbiddenZoneCollidedAlarmCodeField = new ByteField(NotUsedAlarmCodeField13, 4);
            FarForbiddenZoneCollidedAlarmCodeField = new ByteField(NearForbiddenZoneCollidedAlarmCodeField, 4);
            RightForbiddenZoneCollidedAlarmCodeField = new ByteField(FarForbiddenZoneCollidedAlarmCodeField, 4);
            LeftForbiddenZoneCollidedAlarmCodeField = new ByteField(RightForbiddenZoneCollidedAlarmCodeField, 4);

            Debug.Assert(36 << 3 == (int)NotUsedAlarmCodeField10.Index);
            Debug.Assert((36 << 3) + 4 == (int)NotUsedAlarmCodeField11.Index);
            Debug.Assert(37 << 3 == (int)NotUsedAlarmCodeField12.Index);
            Debug.Assert((37 << 3) + 4 == (int)NotUsedAlarmCodeField13.Index);
            Debug.Assert(38 << 3 == (int)NearForbiddenZoneCollidedAlarmCodeField.Index);
            Debug.Assert((38 << 3) + 4 == (int)FarForbiddenZoneCollidedAlarmCodeField.Index);
            Debug.Assert(39 << 3 == (int)RightForbiddenZoneCollidedAlarmCodeField.Index);
            Debug.Assert((39 << 3) + 4 == (int)LeftForbiddenZoneCollidedAlarmCodeField.Index);

            /*
             * 以下
             * 障碍物碰撞报警编码
             */
            NotUsedAlarmCodeField14 = new ByteField(LeftForbiddenZoneCollidedAlarmCodeField, 4);
            NotUsedAlarmCodeField15 = new ByteField(NotUsedAlarmCodeField14, 4);
            NotUsedAlarmCodeField16 = new ByteField(NotUsedAlarmCodeField15, 4);
            LowObstacleCollidedAlarmCodeField = new ByteField(NotUsedAlarmCodeField16, 4);
            NearObstacleCollidedAlarmCodeField = new ByteField(LowObstacleCollidedAlarmCodeField, 4);
            FarObstacleCollidedAlarmCodeField = new ByteField(NearObstacleCollidedAlarmCodeField, 4);
            RightObstacleCollidedAlarmCodeField = new ByteField(FarObstacleCollidedAlarmCodeField, 4);
            LeftObstacleCollidedAlarmCodeField = new ByteField(RightObstacleCollidedAlarmCodeField, 4);

            Debug.Assert(40 << 3 == (int)NotUsedAlarmCodeField14.Index);
            Debug.Assert((40 << 3) + 4 == (int)NotUsedAlarmCodeField15.Index);
            Debug.Assert(41 << 3 == (int)NotUsedAlarmCodeField16.Index);
            Debug.Assert((41 << 3) + 4 == (int)LowObstacleCollidedAlarmCodeField.Index);
            Debug.Assert(42 << 3 == (int)NearObstacleCollidedAlarmCodeField.Index);
            Debug.Assert((42 << 3) + 4 == (int)FarObstacleCollidedAlarmCodeField.Index);
            Debug.Assert(43 << 3 == (int)RightObstacleCollidedAlarmCodeField.Index);
            Debug.Assert((43 << 3) + 4 == (int)LeftObstacleCollidedAlarmCodeField.Index);

            /*
             * 以下
             * 继电输出编码
             */
            RightRelayOutPutCodeField = new ByteField(LeftObstacleCollidedAlarmCodeField, 4);
            LeftRelayOutPutCodeField = new ByteField(RightRelayOutPutCodeField, 4);
            NearRelayOutPutCodeField = new ByteField(LeftRelayOutPutCodeField, 4);
            FarRelayOutPutCodeField = new ByteField(NearRelayOutPutCodeField, 4);
            LowRelayOutPutCodeField = new ByteField(FarRelayOutPutCodeField, 4);
            HighRelayOutPutCodeField = new ByteField(LowRelayOutPutCodeField, 4);
            NotUsedRelayOutPutCodeField1 = new ByteField(HighRelayOutPutCodeField, 4);
            NotUsedRelayOutPutCodeField2 = new ByteField(NotUsedRelayOutPutCodeField1, 4);

            Debug.Assert(44 << 3 == (int)RightRelayOutPutCodeField.Index);
            Debug.Assert((44 << 3) + 4 == (int)LeftRelayOutPutCodeField.Index);
            Debug.Assert(45 << 3 == (int)NearRelayOutPutCodeField.Index);
            Debug.Assert((45 << 3) + 4 == (int)FarRelayOutPutCodeField.Index);
            Debug.Assert(46 << 3 == (int)LowRelayOutPutCodeField.Index);
            Debug.Assert((46 << 3) + 4 == (int)HighRelayOutPutCodeField.Index);
            Debug.Assert(47 << 3 == (int)NotUsedRelayOutPutCodeField1.Index);
            Debug.Assert((47 << 3) + 4 == (int)NotUsedRelayOutPutCodeField2.Index);

            /*
             * CRC
             */
            CRCField = new UShortField(NotUsedRelayOutPutCodeField2);
            Debug.Assert(48 << 3 == (int)CRCField.Index);
        }

        new void InitFieldValue()
        {
            base.InitFieldValue();
            FrameType = _Key;
            InfoLength = EvalInfoLength(); // 因为要在构造函数中运行，所以不能用虚拟方法
        }
    }
}
